#!/bin/sh
# Build script for the project.
# For details on the basic form of this script, see https://notabug.org/akkartik/basic-build.

set -e  # stop immediately on error

## prologue: environment defaults
test "$CC" || export CC=cc
test "$CFLAGS" || export CFLAGS="-g -O3"
# some additional flags for safety
export CFLAGS="$CFLAGS -std=c99 -Wall -Wextra -ftrapv -fno-strict-aliasing"

## helpers
# {{{

# noisily signal success if $1 is older than _any_ of the remaining args
older_than() {
  local target=$1
  shift
  if [ ! -e $target ]
  then
    echo "updating $target" >&2
    return 0  # success
  fi
  local f
  for f in $*
  do
    if [ $f -nt $target ]
    then
      echo "updating $target" >&2
      return 0  # success
    fi
  done
  return 1  # failure
}

# noisily switch directories, as a sort of section heading to group older_than blocks
noisy_cd() {
  cd $1
  echo "-- `pwd`" >&2
}

# redirect to $1, unless it's already identical
update() {
  if [ ! -e $1 ]
  then
    cat > $1
  else
    cat > $1.tmp
    diff -q $1 $1.tmp >/dev/null  &&  rm $1.tmp  ||  mv $1.tmp $1
  fi
}
# }}}

## body: things to generate, what they depend on, and how to generate them from their dependencies

# auto-generate a list of function prototypes
grep -h "^[^ #].*) {" *.c  |sed 's/ {.*/;/'  |update function_list

# auto-generate a list of test names
grep -h "^\s*void test_" *.c  |sed 's/^\s*void \(.*\)(void) {.*/\1,/'  |update test_list
grep -h "^\s*void test_" *.c  |sed 's/^\s*void \(.*\)(void) {.*/"\1",/'  |update test_name_list

older_than a.out *.c *.h function_list test_list && {
  $CC $CFLAGS *.c
}

## epilogue
# if we got to the end, signal success
# otherwise you incorrectly signal failure when the final target is not older_than its dependencies
exit 0
